package com.brainhealth.customer.service.impl;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson2.JSONObject;
import com.brainhealth.common.constant.*;
import com.brainhealth.common.core.redis.RedisCache;
import com.brainhealth.common.enums.*;
import com.brainhealth.common.utils.*;
import com.brainhealth.customer.config.MinioConfig;
import com.brainhealth.customer.domain.*;
import com.brainhealth.customer.domain.vo.ChatRecordVO;
import com.brainhealth.customer.domain.vo.ChatVO;
import com.brainhealth.customer.service.*;
import com.brainhealth.utils.CommonUtils;
import io.jsonwebtoken.lang.Assert;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author wll
 * 青竹聊天
 */
@Service
public class ChatServiceImpl implements IChatService {
    /**
     * 日志
     */
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    MinioConfig minioConfig;

    @Autowired
    IChatTemplateService chatTemplateService;

    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IChatRecordService chatRecordService;

    @Autowired
    private IChatMainService chatMainService;

    @Autowired
    private ICustomerService customerService;

    @Autowired
    private ChatIDService chatIDService;

    @Autowired
    private ChatContentService chatContentService;

    /**
     * 订单
     */
    @Autowired
    private IExerciseOrderService exerciseOrderService;

    /**
     * 会员训练记录
     */
    @Autowired
    private ICustomerExerciseService customerExerciseService;

    @Autowired
    private IExerciseService exerciseService;

    @Autowired
    IWebsocketService websocketService;

    @Autowired
    ISysLoginPushService sysLoginPushService;

    @Override
    public int getChatStatus(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        Customer customer = CommonUtils.getCustomerByRequest(request);
        if (null==customer){
            logger.warn("{}，用户信息为空",ts);
        }
        ExerciseOrder exerciseOrderParam = new ExerciseOrder();
        exerciseOrderParam.setStatus(PayStatus.Exercise);
        ExerciseOrder exerciseOrder = exerciseOrderService.getCustomerExerciseOrder(customer, exerciseOrderParam);

        exerciseOrderParam.setStatus(PayStatus.Finish);
        ExerciseOrder finishExerciseOrder = exerciseOrderService.getCustomerExerciseOrder(customer, exerciseOrderParam);

        //训练中订单未完成、已完成、已过期
        List<CustomerExercise> notFinishedCustomerExerciseList = customerExerciseService.getCustomerExerciseList(customer, CustomerExerciseStatus.NoFinish);
        List<CustomerExercise> finishedCustomerExerciseList = customerExerciseService.getCustomerExerciseList(customer, CustomerExerciseStatus.Finished);
        List<CustomerExercise> expiredCustomerExerciseList = customerExerciseService.getCustomerExerciseList(customer, CustomerExerciseStatus.expired);

        String orderNo= null!=exerciseOrder? exerciseOrder.getOrderId():finishExerciseOrder.getOrderId();

        Long countSort = getCustomerCountSort(customer, null, notFinishedCustomerExerciseList, finishedCustomerExerciseList, expiredCustomerExerciseList);

        ChatMain chatMain = new ChatMain();
        chatMain.setCustomerId(customer.getCustomerId());
        chatMain.setOrderNo(orderNo);
        List<ChatMain> chatMains = chatMainService.selectChatMainList(chatMain);
        if (CollectionUtils.isEmpty(chatMains)) {
            logger.warn("{}，最后一条聊天记录为空", ts);
            return ChatStatusEnum.NEXT_COURSE_OPEN.getCode();
        }

        boolean closeFlag =DateUtils.differentHoursByMillisecond(new Date(), chatMains.get(0).getLeastChatTime()) > NumberConstants.SEVEN;

        //锁定青竹
        CustomerExercise  customerExercise=new CustomerExercise();
        customerExercise.setCustomerId(customer.getCustomerId());
        customerExercise.setOrderId(orderNo);
        customerExercise.setCountSort(countSort);
        customerExercise.setStatus(CustomerExerciseStatus.expired);
        List<CustomerExercise> customerExerciseList = customerExerciseService.selectCustomerExerciseList(customerExercise);
        //第28课过期，将订单置为已完成
        //第28课过期，无训练中订单（新订单）锁定青竹
        if (CollectionUtils.isEmpty(notFinishedCustomerExerciseList)
                && exerciseService.getCompletedState(finishedCustomerExerciseList,expiredCustomerExerciseList)
                && CollectionUtils.isNotEmpty(customerExerciseList)
                && null == exerciseOrder) {
            return ChatStatusEnum.CURRENT_ORDER_OVER_AND_NEXT_NEVER_OUT_EIGHT.getCode();
        }

        //没有当前订单，超过8小时，关闭青竹

        //一、无当前订单（）
        //当前课程已完成& 当前课程结束超过8小时& 无下次课程=> 关闭青竹
        if (CollectionUtils.isEmpty(notFinishedCustomerExerciseList)
                && exerciseService.getCompletedState(finishedCustomerExerciseList, expiredCustomerExerciseList)
                && closeFlag
                && null == exerciseOrder) {
            if (Long.valueOf(NumberConstants.NEGATIVE_ONE).equals(customer.getMechanismId())) {
                return ChatStatusEnum.CURRENT_ORDER_OVER_AND_NEXT_NEVER_OUT_EIGHT_EXPERIENCE_USER.getCode();
            }
            return ChatStatusEnum.CURRENT_ORDER_OVER_AND_NEXT_NEVER_OUT_EIGHT.getCode();
        }
        //当前课程已完成& 当前课程结束8小时内& 无下次课程=> 欢迎回来
        if (CollectionUtils.isEmpty(notFinishedCustomerExerciseList)
                && exerciseService.getCompletedState(finishedCustomerExerciseList,expiredCustomerExerciseList)
                && !closeFlag
                && null == exerciseOrder){
            return ChatStatusEnum.CURRENT_ORDER_OVER_AND_NEXT_NEVER_IN_EIGHT.getCode();
        }

        //第1次，无主回话逻辑

        //下一课程是否开启 - 当前未完成的课程
        boolean nextExerciseStatus= chatIDService.getExerciseStatus(notFinishedCustomerExerciseList);

        //->切订单逻辑判断
        //下一课程已开启（不论当前课程是否结束，当前聊天是否结束）
        if (CollectionUtils.isNotEmpty(notFinishedCustomerExerciseList)
              && null!= chatMains.get(0).getCourseNo()
              && null != notFinishedCustomerExerciseList.get(0).getCountSort()
              && (chatMains.get(0).getCourseNo() < notFinishedCustomerExerciseList.get(0).getCountSort() && nextExerciseStatus)) {
            //日期打招呼
            return 1;
        }

        //欢迎回来
        return 0;
    }

    @Override
    public ChatVO getNextChat(HttpServletRequest request, ChatQueryParam chatQueryParam) {
        long ts = DateUtils.getTimeMillis();
        logger.info("ts:{},获取下次聊天内容,入参{}", ts, chatQueryParam);
        checkChatQueryParam(chatQueryParam);
        Customer customer = CommonUtils.getCustomerByRequest(request);

        ChatBase chatBase = getChatBase(request);
        List<CustomerExercise> notFinishedCustomerExerciseList = chatBase.getNotFinishedCustomerExerciseList();
        List<CustomerExercise> finishedCustomerExerciseList = chatBase.getFinishedCustomerExerciseList();
        List<CustomerExercise> expiredCustomerExerciseList = chatBase.getExpiredCustomerExerciseList();
        Long countSort = chatBase.getCourseNo();
        customer.setCountSort(countSort);
        logger.info("ts:{},用户ID:{} ，昵称:{}，课程编号：{}，【查询聊天内容】入参:{}", ts, customer.getCustomerId(), customer.getNickName(), customer.getCountSort(), chatQueryParam);
        //TODO 异常的处理checkChatQueryParam(chatQueryParam);
        List<ChatTemplate> chatList = chatTemplateService.getChatTemplateListByCache();
        chatIDService.handChatId(chatQueryParam, customer, chatList,chatBase);
        Long chatId = chatQueryParam.getLongChatId();
        Integer answerType = getAnswerType(chatQueryParam);
        List<ChatTemplate> chatTemplateList = chatList.stream().filter(item -> item.getChatId().equals(chatId))
                .filter(item -> answerType == item.getAnswerType())
                .collect(Collectors.toList());
        logger.info("ts:{},模板条数{}", ts, chatTemplateList.size());
        return chatContentService.getChatVo(chatTemplateList, chatQueryParam, customer,notFinishedCustomerExerciseList,finishedCustomerExerciseList,expiredCustomerExerciseList);
    }

    private Long getCustomerCountSort(Customer customer, ChatQueryParam chatQueryParam, List<CustomerExercise> notFinishedCustomerExerciseList, List<CustomerExercise> finishedCustomerExerciseList,List<CustomerExercise> expiredCustomerExerciseList) {
        //白名单用户 ==》完成所有聊天

        if (CollectionUtils.isEmpty(notFinishedCustomerExerciseList) && CollectionUtils.isEmpty(finishedCustomerExerciseList)) {
            logger.warn("用户ID:{}昵称:{}，无已完成训练，无未开启训练", customer.getCustomerId(), customer.getNickName());
        }

        //如果未开始
        if (CollectionUtils.isEmpty(finishedCustomerExerciseList)) {
            return customer.getCountSort();
        }

        //如果完成全部训练
        if (CollectionUtils.isEmpty(notFinishedCustomerExerciseList) && exerciseService.getCompletedState(finishedCustomerExerciseList,expiredCustomerExerciseList)) {
            return customer.getCountSort();
        }

        // 22 -> 23 未学完前
        OptionalLong min = notFinishedCustomerExerciseList.stream().mapToLong(CustomerExercise::getCustomerExerciseId).min();
        notFinishedCustomerExerciseList = notFinishedCustomerExerciseList.stream().filter(item -> item.getCustomerExerciseId() == min.getAsLong()).collect(Collectors.toList());
        CustomerExercise customerExercise = notFinishedCustomerExerciseList.get(0);
        if (DateUtils.compare(new Date(), customerExercise.getOpenTime())) {
            return customer.getCountSort();
        }

        OptionalLong max = finishedCustomerExerciseList.stream().mapToLong(CustomerExercise::getCustomerExerciseId).max();
        finishedCustomerExerciseList = finishedCustomerExerciseList.stream().filter(item -> item.getCustomerExerciseId() == max.getAsLong()).collect(Collectors.toList());
        CustomerExercise finishedCustomerExercise = finishedCustomerExerciseList.get(0);
        return finishedCustomerExercise.getCountSort();
    }

    private void checkChatQueryParam(ChatQueryParam chatQueryParam) {
        Assert.state(ChatIdEnum.checkCheckId(chatQueryParam.getChatId()), "聊天模板ID入参错误");
        Assert.state(checkSex(chatQueryParam.getSex()), "性别取值不正确");
    }

    private boolean checkSex(String sex) {
        if (StringUtils.isNotBlank(sex)) {
            List<String> sexCodeList = SexEnum.getSexCodeList();
            return sexCodeList.contains(sex);
        }
        return true;
    }

    private Integer getAnswerType(ChatQueryParam chatQueryParam) {
        if (StringUtils.isBlank(chatQueryParam.getName())
                && null == chatQueryParam.getAge()
        ) {
            return chatQueryParam.getAnswerType();
        }

        String name = chatQueryParam.getName();
        boolean result = false;
        if (StringUtils.isNotBlank(name)) {
            String pattern = "[\\u4e00-\\u9fa5a-zA-Z]{1,10}";
            result = Pattern.compile(pattern).matcher(name).matches();
        }
        Integer age = chatQueryParam.getAge();
        if (null != age) {
            String agePattern = "[2-9][0-9]|100";
            result = Pattern.compile(agePattern).matcher(String.valueOf(age)).matches();
        }

        return result ? AnswerTypeEnum.RIGHT.getCode() : AnswerTypeEnum.NOT_RIGHT.getCode();
    }

    @Override
    @Transactional
    public int saveChatRecord(HttpServletRequest request, ChatParam chatParam) {
        long ts = DateUtils.getTimeMillis();
        Customer customer = CommonUtils.getCustomerByRequest(request);
        logger.info("ts:{}用户ID:{} ，昵称:{}，[保存聊天内容]，入参:{}", ts, customer.getCustomerId(), customer.getNickName(), chatParam);
        TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
        try {
            checkParam(chatParam);
            ChatRecord chatRecord = getChatRecord(customer, chatParam);

            CustomerChatStatus chatStatus = customer.getChatStatus();
            if (chatStatus == CustomerChatStatus.Register) {
                //1.更新用户基础信息(用户昵称、年龄、性别)
                if (StringUtils.isNotBlank(chatParam.getName())
                        && RegexUtil.isValidNickName(chatParam.getName())) {
                    customer.setNickName(chatParam.getName());
                    boolean result = customerService.updateCustomerInfo(customer);
                    logger.info("ts:{},[保存聊天内容]，[保存用户昵称]，结果:{}", ts, result);
                    if (!result) {
                        return NumberConstants.NEGATIVE_ONE;
                    }
                }
                if (null != chatParam.getAge()) {
                    customer.setAge(Long.valueOf(chatParam.getAge()));
                    boolean result = customerService.updateCustomerInfo(customer);
                    logger.info("ts:{},[保存聊天内容]，[保存用户年龄]，结果:{}", ts, result);
                    if (!result) {
                        return NumberConstants.NEGATIVE_ONE;
                    }
                }
                if (null != chatParam.getSex()) {
                    customer.setSex(Long.valueOf(chatParam.getSex()));
                    boolean result = customerService.updateCustomerInfo(customer);
                    logger.info("ts:{},[保存聊天内容]，[保存用户性别]，结果:{}", ts, result);
                    if (!result) {
                        return NumberConstants.NEGATIVE_ONE;
                    }
                }
                //2.更新用户状态
                customer = customerService.selectCustomerByCustomerId(chatRecord.getCustomerId());
                if (null != customer
                        && StringUtils.isNotBlank(customer.getNickName())
                        && null != customer.getAge()
                        && null != customer.getSex()
                ) {
                    customer.setChatStatus(CustomerChatStatus.Init);
                    boolean result = customerService.updateCustomerInfo(customer);
                    logger.info("ts:{},[保存聊天内容]，[更新用户状态]，结果:{}", ts, result);
                    if (!result) {
                        return NumberConstants.NEGATIVE_ONE;
                    }
                }
            }

            // 第28次课，做完训练，更新 open_time
            List<CustomerExercise> finishedCustomerExerciseList = customerExerciseService.getCustomerExerciseList(customer, CustomerExerciseStatus.Finished);
            if(CollectionUtils.isNotEmpty(finishedCustomerExerciseList)){
                finishedCustomerExerciseList = finishedCustomerExerciseList.stream().sorted(Comparator.comparing(CustomerExercise::getCustomerExerciseId).reversed()).collect(Collectors.toList());
            }
            List<CustomerExercise> expiredCustomerExerciseList = customerExerciseService.getCustomerExerciseList(customer, CustomerExerciseStatus.expired);

            if (NextChatFlagConstants.CHAT_NEXT.equals(chatParam.getNextChatFlag())) {
                if (exerciseService.getCompletedState(finishedCustomerExerciseList,expiredCustomerExerciseList)) {
                    CustomerExercise customerExercise = finishedCustomerExerciseList.get(NumberConstants.ZERO);
                    logger.info("ts:{},[保存聊天内容]，[切换订单]，当前完成课程:{}", ts,customerExercise);
                    boolean result = customerExerciseService.customerOrderReset( customer,customerExercise);
                    //result=false 没有新订单，将当前订单状态置为已完成
                    //result=true  将当前订单状态置为已完成，有新订单，，将下个订单状态置为训练中
                    logger.info("ts:{},[保存聊天内容]，[切换订单]，切换结果:{}", ts, result);
                }else{
                    // CustomerExercise customerExercise = finishedCustomerExerciseList.get(NumberConstants.ZERO);
                    // logger.info("ts:{},[保存聊天内容]，[切换课程]，当前完成课程:{}", ts,customerExercise);
                    // boolean result = customerExerciseService.customerExerciseNextReset(customerExercise, customer);
                    // logger.info("ts:{},[保存聊天内容]，[切换课程]，切换结果:{}", ts, result);
                    // if (!result) {
                    //     return NumberConstants.NEGATIVE_ONE;
                    // }
                }
            }

            //3.保存聊天记录
            // -> 处理DATE循环发送问题
            if (NextChatFlagConstants.DATE.equals(chatParam.getChatFlag())){
                logger.info("ts:{}, 保存时处理聊天记录", ts);
                chatRecord.setChatType(Integer.valueOf(ChatContentTypeEnum.MAIN.getCode()));
                chatParam.setChatType(Integer.valueOf(ChatContentTypeEnum.MAIN.getCode()));
            }
            int result = chatRecordService.insertChatRecord(chatRecord);
            if (Integer.valueOf(ChatContentTypeEnum.MAIN.getCode()).equals(chatParam.getChatType())) {
                //4.保存聊天主表
                ChatMain chatMain = new ChatMain();
                chatMain.setCustomerId(customer.getCustomerId());
                chatMain.setOrderNo(chatParam.getOrderNo());
                chatMain.setCourseNo(chatParam.getCourseNo());
                chatMain.setContent(chatRecord.getRecordContent());
                chatMain.setLeastChatTime(chatRecord.getCreateTime());
                if  (exerciseService.getCompletedState(finishedCustomerExerciseList, expiredCustomerExerciseList)){
                    Date date = DateUtils.addHours(new Date(), NumberConstants.EIGHT);
                    if (null!=customer.getMechanismId()){
                        date = DateUtils.addMilliseconds(new Date(), NumberConstants.TEN);
                    }
                    chatMain.setNextOpenTime(date);
                }
                chatMainService.onDuplicateUpdateChatMain(chatMain);
            }
            logger.info("ts:{},[保存聊天内容]，[保存聊天记录]{}", ts, result);
            platformTransactionManager.commit(transactionStatus);
            return result;
        } catch (Exception e) {
            logger.info("ts:{},[保存聊天内容]，异常", ts, e);
            platformTransactionManager.rollback(transactionStatus);
            return NumberConstants.NEGATIVE_ONE;
        }
    }

    private void checkParam(ChatParam chatParam) {
        Assert.notNull(chatParam.getContent(), "聊天内容不能为空");
        Assert.notNull(chatParam.getRole(), "用户角色不能为空");
        Assert.state(checkRole(chatParam.getRole()), "用户角色取值不正确");
        Assert.notNull(chatParam.getInputType(), "消息类型不能为空");
        Assert.state(checkInputType(chatParam.getInputType()), "消息类型取值不正确");
        Assert.notNull(chatParam.getOrderNo(), "订单编号不能为空");
        Assert.notNull(chatParam.getNextChatFlag(), "下一个聊天ID不能为空");
        Assert.notNull(chatParam.getCourseNo(), "课程编号不能为空");
        Assert.notNull(chatParam.getChatFlag(), "聊天模板标识不能为空");
    }

    private boolean checkRole(Long role) {
        List<Integer> roleCodeList = RoleEnum.getRoleCodeList();
        return roleCodeList.contains(role.intValue());
    }

    private boolean checkInputType(Integer inputType) {
        List<Integer> inputTypeCodeList = InputTypeEnum.getInputTypeCodeList();
        return inputTypeCodeList.contains(inputType);
    }

    private ChatRecord getChatRecord(Customer customer, ChatParam chatParam) {
        if (null == chatParam) {
            return null;
        }
        ChatRecord chatRecord = new ChatRecord();
        BeanUtils.copyProperties(chatParam, chatRecord);
        chatRecord.setCustomerId(customer.getCustomerId());
        String chatContent = getContent(chatParam);
        chatRecord.setContent(chatContent);
        String recordChatContent=getRecordContent(chatParam);
        chatRecord.setRecordContent(recordChatContent);
        chatRecord.setCreateTime(DateUtils.getNowDate());
        return chatRecord;
    }


    private String getContent(ChatParam chatParam) {
        ChatContent chatContent = new ChatContent();
        BeanUtils.copyProperties(chatParam, chatContent);
        JSONObject jsonObject = JSONObject.from(chatContent);
        String jsonString = jsonObject.toJSONString(jsonObject);
        return jsonString;
    }

    private String getRecordContent(ChatParam chatParam) {
        ChatRecordContent chatContent = new ChatRecordContent();
        BeanUtils.copyProperties(chatParam, chatContent);
        JSONObject jsonObject = JSONObject.from(chatContent);
        String jsonString = jsonObject.toJSONString(jsonObject);
        return jsonString;
    }

    @Override
    public List<ChatRecordVO> getChatList(HttpServletRequest request) {
        Customer customer = CommonUtils.getCustomerByRequest(request);
        ExerciseOrder exerciseOrder = exerciseOrderService.getExerciseOrder(customer);
        ChatRecord chatRecord = new ChatRecord();
        chatRecord.setCustomerId(customer.getCustomerId());
        chatRecord.setOrderNo(exerciseOrder.getOrderId());

        List<ChatRecord> chatRecordList = chatRecordService.selectChatRecordList(chatRecord);
        List<ChatRecordVO> chatRecordVoList = getChatRecordVoList(chatRecordList);
        return chatRecordVoList;
    }

    @Override
    public ChatBase getChatBase(HttpServletRequest request) {
        Customer customer = CommonUtils.getCustomerByRequest(request);
        if (null == customer) {
            logger.warn("getChatBase，用户信息为空");
        }
        Long customerId = customer.getCustomerId();

        ExerciseOrder exerciseOrderParam = new ExerciseOrder();
        exerciseOrderParam.setStatus(PayStatus.Exercise);
        ExerciseOrder exerciseOrder = exerciseOrderService.getCustomerExerciseOrder(customer, exerciseOrderParam);

        exerciseOrderParam.setStatus(PayStatus.Finish);
        ExerciseOrder finishExerciseOrder = exerciseOrderService.getCustomerExerciseOrder(customer, exerciseOrderParam);

        //训练中订单未完成、已完成、已过期
        List<CustomerExercise> notFinishedCustomerExerciseList = customerExerciseService.getCustomerExerciseList(customer, CustomerExerciseStatus.NoFinish);
        List<CustomerExercise> finishedCustomerExerciseList = customerExerciseService.getCustomerExerciseList(customer, CustomerExerciseStatus.Finished);
        List<CustomerExercise> expiredCustomerExerciseList = customerExerciseService.getCustomerExerciseList(customer, CustomerExerciseStatus.expired);
        String orderNo = null != exerciseOrder ? exerciseOrder.getOrderId() : finishExerciseOrder.getOrderId();
        Long countSort = getCustomerCountSort(customer, null, notFinishedCustomerExerciseList, finishedCustomerExerciseList, expiredCustomerExerciseList);

        ChatBase chatBase=new ChatBase();
        chatBase.setCustomerId(customerId);
        chatBase.setOrderNo(orderNo);
        chatBase.setCourseNo(countSort);
        chatBase.setNotFinishedCustomerExerciseList(notFinishedCustomerExerciseList);
        chatBase.setFinishedCustomerExerciseList(finishedCustomerExerciseList);
        chatBase.setExpiredCustomerExerciseList(expiredCustomerExerciseList);

        return chatBase;
    }

    private List<ChatRecordVO> getChatRecordVoList(List<ChatRecord> chatRecordList) {
        if (CollectionUtils.isEmpty(chatRecordList)) {
            return null;
        }
        List<ChatRecordVO> chatRecordVOList = new ArrayList<>(chatRecordList.size());
        for (ChatRecord chatRecord : chatRecordList) {
            String content = chatRecord.getContent();
            ChatContent chatContent = JSONObject.parseObject(content, ChatContent.class);
            ChatRecordVO recordVO = new ChatRecordVO();
            BeanUtils.copyProperties(chatRecord, recordVO);
            BeanUtils.copyProperties(chatContent, recordVO);
            String strDate = DateCalcUtils.getDateToString(chatRecord.getCreateTime());
            recordVO.setCreateDate(strDate);
            recordVO.setNextChatFlag(chatRecord.getNextChatFlag());

            chatRecordVOList.add(recordVO);
        }
        return chatRecordVOList;
    }

    @Override
    public long refreshChatTemplate() {
        logger.info("初始化聊天模板数据开始");

        String cacheKey = CacheConstants.CHAT_TEMPLATE_KEY;
        List<ChatTemplate> cacheValue = chatTemplateService.selectChatTemplateList(null);
        int size = CollectionUtils.isEmpty(cacheValue) ? 0 : cacheValue.size();
        logger.info("聊天模板数据条数：{}", size);
        long setResult = redisCache.refreshCache(cacheKey, cacheValue);
        logger.info("新增缓存结果{}", setResult);

        logger.info("初始化聊天模板数据结束");
        return setResult;
    }

    @Override
    public HelloChat sayHello(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        Customer customer = CommonUtils.getCustomerByRequest(request);
        if (null == customer) {
            return null;
        }
        String nickName = customer.getNickName();
        logger.info("ts：{}，【打招呼】，用户：{}", ts, customer.getNickName());
        HelloChat helloChat = new HelloChat();
        List<ChatTemplate> cacheList = chatTemplateService.getChatTemplateListByCache();
        ChatTemplate chatTemplate = getRandomContent(ts, cacheList, ChatCategoryEnum.CLICK_AI_ROBOT.getCategory1Code(), nickName);
        helloChat.setHelloMsg(chatTemplate.getContent());
        chatTemplate = getRandomContent(ts, cacheList, ChatCategoryEnum.CLICK_AI_ROBOT_BACKGROUND.getCategory1Code(), nickName);
        helloChat.setImage(chatTemplate.getContent());
        helloChat.setStaticImage(chatTemplate.getWaveUrl());

        return helloChat;
    }

    private ChatTemplate getRandomContent(Long ts,List<ChatTemplate> cacheList,Integer categoryCode,String nickName)
    {
        List<ChatTemplate> chatTemplateList = cacheList.stream().filter(item -> item.getChatCategory1Id() == categoryCode).collect(Collectors.toList());
        Random rand = new Random();
        int randomIndex = rand.nextInt(chatTemplateList.size());
        logger.info("ts{},随机索引：{}", ts, randomIndex);
        ChatTemplate chatTemplate = chatTemplateList.get(randomIndex);
        if (chatTemplate.getIsPlaceholderContent() == 1) {
            logger.info("ts{},获取可替换随机内容。模板内容：{}，替换内容：{}", ts, chatTemplate.getContent(), nickName);
            chatTemplate.setContent(chatTemplate.getContent().replace(Constants.MARK_NAME, nickName));
        }

        return chatTemplate;
    }

    @Override
    public void clearChatRecord() {
        long tid = DateUtils.getTimeMillis();
        Date beginDate = new Date();
        logger.info("tid：{},【清理聊天记录】,开始时间：{}", tid, DateUtils.getTime());
        List<String> customerIdList = chatRecordService.selectCustomerIdList();
        if (CollectionUtils.isEmpty(customerIdList)) {
            return;
        }
        logger.info("tid：{},【清理聊天记录】,用户数：{}", tid, customerIdList.size());
        for (String customerId : customerIdList) {
            List<String> recordIdList = chatRecordService.selectRecordIdList(Long.valueOf(customerId));
            String[] recordIdArr = recordIdList.toArray(new String[recordIdList.size()]);
            Long[] longRecordIdArr = Convert.toLongArray(recordIdArr);
            if (null != longRecordIdArr && longRecordIdArr.length > 0) {
                int count = chatRecordService.deleteChatRecordByIds(longRecordIdArr);
                logger.info("tid：{},【清理聊天记录】,用户：{}, 清理聊天记录条数：{}", tid, customerId, count);
            }
        }
        logger.info("tid：{},【清理聊天记录】,结束时间：{}", tid, DateUtils.getTime());
        Date endDate = new Date();
        logger.info("tid：{},【清理聊天记录】,耗时：{}", tid, DateUtils.differentMinuteByMillisecond(beginDate, endDate));
    }


    public void pushLogin() {
        long ts = DateUtils.getTimeMillis();
        try {
            logger.info("ts:{}，登录消息推送开始", ts);
            List<Customer> onlineCustomerList = websocketService.getOnlineCustomerList();
            List<SysLoginPush> sysLoginPushList = sysLoginPushService.selectSysLoginPushList(null);
            for (SysLoginPush loginPush : sysLoginPushList) {
                Integer pushSwitch = loginPush.getPushSwitch();
                if (pushSwitch.equals(YNEnum.NO.getCode())) {
                    continue;
                }
                Long taskId = loginPush.getTaskId();
                String pushContent = loginPush.getPushContent();
                Integer pushUserType = loginPush.getPushUserType();
                String pushUsers = loginPush.getPushUser();
                Integer pushCondition = loginPush.getPushCondition();
                List<Customer> customerList = getSettingPushUserList(pushUserType, pushUsers);
                List<Customer> pushUserList = getPushUserList(onlineCustomerList, customerList, pushCondition);
                for (Customer customer : pushUserList) {
                    String customerPhone = customer.getPhone();
                    String cacheKey = String.format("%s:%s:%s", CacheConstants.PUSH_LOGIN_KEY, taskId, customerPhone);
                    Object cacheObject = redisCache.getCacheObject(cacheKey);
                    if (null == cacheObject) {
                        if (StringUtils.isNotBlank(pushContent)) {
                            pushContent = pushContent.replace(Constants.MARK_NAME, customer.getNickName());
                        }
                        websocketService.pushMsgToOne(customerPhone, pushContent);
                        logger.info("ts:{}用户ID：{}登录消息推送完成", ts, customer.getPhone());
                        redisCache.setCacheObject(cacheKey, Constants.PUSH_LOGIN_FLAG);
                        logger.info("ts:{}用户ID：{}登录消息推送，写入缓存成功，缓存KEY：{}", ts, customerPhone, cacheKey);
                    }
                }
            }
            logger.info("ts:{}，登录消息推送结束", ts);
        } catch (Exception e) {
            logger.error("ts:{},登录推送异常，", ts, e);
        }
    }

    private List<Customer> getSettingPushUserList(Integer pushUserType, String userIds) {
        if (pushUserType.equals(PushUserTypeEnum.ALL.getCode())) {
            return customerService.selectCustomerList(null);
        }
        String[] ids = userIds.split(PunctuationConstants.COMMA);
        List<String> idArr = Arrays.asList(ids);
        List<Long> longIdList = LongUtils.string2LongList(idArr);
        return customerService.selectCustomerByCustomerIds(longIdList);
    }

    private List<Customer> getPushUserList(List<Customer> onlineCustomerList, List<Customer> customerList, Integer logoutDays) {
        List<Customer> customerIdList = new ArrayList<>();
        List<Customer> intersection = onlineCustomerList.stream().filter(item -> customerList.contains(item)).collect(Collectors.toList());
        for (Customer customer : intersection) {
            Date date = new Date();
            Date loginTime = customer.getLoginTime();
            int days = DateUtils.differentDaysByMillisecond(loginTime, date);
            if (logoutDays == days) {
                customerIdList.add(customer);
            }
        }
        return customerIdList;
    }

    @Override
    public void openNextTask() {
        long ts = DateUtils.getTimeMillis();
        try {
            logger.info("ts:{} 开启下一订单任务开始=====================================",ts);
            List<ChatMain> chatMainList = chatMainService.selectChatMainList(null);
            if (io.jsonwebtoken.lang.Collections.isEmpty(chatMainList)) {
                logger.info("{} 未查询到聊天主表数据", ts);
                return;
            }

            for (ChatMain chatMain : chatMainList) {

                Customer customer=new Customer();
                customer.setCustomerId(chatMain.getCustomerId());
                CustomerExercise customerExercise = new CustomerExercise();
                customerExercise.setCustomerId(customer.getCustomerId());
                customerExercise.setOrderId(chatMain.getOrderNo());
                customerExercise.setStatus(CustomerExerciseStatus.Finished);
                List<CustomerExercise> finishedCustomerExerciseList = customerExerciseService.selectCustomerExerciseList(customerExercise);
                customerExercise.setStatus(CustomerExerciseStatus.expired);
                List<CustomerExercise> expiredCustomerExerciseList = customerExerciseService.selectCustomerExerciseList(customerExercise);

                if (StringUtils.isNotBlank(chatMain.getOrderNo())
                        && StringUtils.isNotBlank(chatMain.getNextOrderNo())
                        &&  exerciseService.getCompletedState(finishedCustomerExerciseList,expiredCustomerExerciseList)
                        && null != chatMain.getNextOpenTime()
                        && DateUtils.compare(new Date(), chatMain.getNextOpenTime())) {
                    openNextOrderTask(chatMain,ts);
                }
            }

            logger.info("ts:{} 开启下一订单任务结束=====================================",ts);
        } catch (Exception e) {
            logger.error("ts{}，开启下一订单任务异常",ts, e);
        }
    }

    @Transactional
    void openNextOrderTask(ChatMain chatMain,Long ts)
    {
        //1.更新训练中的订单为已完成状态
        ExerciseOrder exerciseOrder = new ExerciseOrder();
        exerciseOrder.setCustomerId(chatMain.getCustomerId());
        exerciseOrder.setOrderId(chatMain.getOrderNo());
        exerciseOrder.setStatus(PayStatus.Exercise);
        List<ExerciseOrder> exerciseOrderList = exerciseOrderService.selectExerciseOrderList(exerciseOrder);
        if (org.springframework.util.CollectionUtils.isEmpty(exerciseOrderList)) {
            logger.info("{} 用户{}无训练中的订单", ts, chatMain.getCustomerId());
        }
        exerciseOrder.setStatus(PayStatus.Finish);
        exerciseOrder.setExerciseOrderId(exerciseOrderList.get(0).getExerciseOrderId());
        int updateExerciseResult = exerciseOrderService.updateExerciseOrder(exerciseOrder);
        logger.info("ts{}，【1】更新订单为完成状态，结果：{}", ts, updateExerciseResult);

        //2.更新已支付订单状态为训练中状态
        exerciseOrder.setOrderId(chatMain.getNextOrderNo());
        exerciseOrder.setStatus(PayStatus.Paid);
        exerciseOrderList = exerciseOrderService.selectExerciseOrderList(exerciseOrder);
        if (org.springframework.util.CollectionUtils.isEmpty(exerciseOrderList)) {
            logger.info("ts{} 用户{}无已支付的订单", ts, chatMain.getCustomerId());
        }
        exerciseOrder.setStatus(PayStatus.Exercise);
        exerciseOrder.setExerciseOrderId(exerciseOrderList.get(0).getExerciseOrderId());
        int updatePaidResult = exerciseOrderService.updateExerciseOrder(exerciseOrder);
        logger.info("ts{}，【2】更新订单为训练中状态，结果：{}", ts, updatePaidResult);

        //3.更新聊天主表
        ChatMain updateChatMain=new ChatMain();
        updateChatMain.setId(chatMain.getId());
        updateChatMain.setNextOpenTime(null);
        updateChatMain.setNextOrderNo("");
        int updateResult = chatMainService.updateChatMain(updateChatMain);
        logger.info("ts{}，【3】更新下一订单及开启状态，结果：{}", ts, updateResult);
    }


}
